home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / f_sharpen.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  7.7 KB  |  258 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <stdio.h>
  19.  
  20. #include "filter.h"
  21. #include "filters.h"
  22. #include "f_convolute.h"
  23. #include "ScriptInterpreter.h"
  24. #include "ScriptValue.h"
  25. #include "ScriptError.h"
  26.  
  27. #define USE_ASM
  28.  
  29. extern "C" void asm_sharpen_run(
  30.         void *dst,
  31.         void *src,
  32.         unsigned long width,
  33.         unsigned long height,
  34.         unsigned long srcstride,
  35.         unsigned long dststride,
  36.         long a_mult,
  37.         long b_mult);
  38.  
  39. #define C_TOPOK        (1)
  40. #define C_BOTTOMOK    (2)
  41. #define C_LEFTOK    (4)
  42. #define C_RIGHTOK    (8)
  43.  
  44. void inline conv_add(long& rt, long& gt, long& bt, unsigned long dv, long m) {
  45.     bt += m*(0xFF & (dv));
  46.     gt += m*(0xFF & (dv>>8));
  47.     rt += m*(0xFF & (dv>>16));
  48. }
  49.  
  50. void inline conv_add2(long& rt, long& gt, long& bt, unsigned long dv) {
  51.     bt += 0xFF & (dv);
  52.     gt += 0xFF & (dv>>8);
  53.     rt += 0xFF & (dv>>16);
  54. }
  55.  
  56. static unsigned long __fastcall do_conv(unsigned long *data, long *m, long sflags, long pit) {
  57.     long rt=0, gt=0, bt=0;
  58.  
  59.     if (sflags & C_TOPOK) {
  60.         if (sflags & (C_LEFTOK))        conv_add2(rt, gt, bt, data[        -1]);
  61.         else                            conv_add2(rt, gt, bt, data[         0]);
  62.                                         conv_add2(rt, gt, bt, data[         0]);
  63.         if (sflags & (C_RIGHTOK))        conv_add2(rt, gt, bt, data[        +1]);
  64.         else                            conv_add2(rt, gt, bt, data[         0]);
  65.     } else {
  66.         if (sflags & (C_LEFTOK))        conv_add2(rt, gt, bt, data[(pit>>2)-1]);
  67.         else                            conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  68.                                         conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  69.         if (sflags & (C_RIGHTOK))        conv_add2(rt, gt, bt, data[(pit>>2)+1]);
  70.         else                            conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  71.     }
  72.     if (sflags & (C_LEFTOK))            conv_add2(rt, gt, bt, data[(pit>>2)-1]);
  73.     else                                conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  74.     if (sflags & (C_RIGHTOK))            conv_add2(rt, gt, bt, data[(pit>>2)+1]);
  75.     else                                conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  76.     if (sflags & C_BOTTOMOK) {
  77.         if (sflags & (C_LEFTOK))        conv_add2(rt, gt, bt, data[(pit>>1)-1]);
  78.         else                            conv_add2(rt, gt, bt, data[(pit>>1)  ]);
  79.                                         conv_add2(rt, gt, bt, data[(pit>>1)  ]);
  80.         if (sflags & (C_RIGHTOK))        conv_add2(rt, gt, bt, data[(pit>>1)+1]);
  81.         else                            conv_add2(rt, gt, bt, data[(pit>>1)  ]);
  82.     } else {
  83.         if (sflags & (C_LEFTOK))        conv_add2(rt, gt, bt, data[(pit>>2)-1]);
  84.         else                            conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  85.                                         conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  86.         if (sflags & (C_RIGHTOK))        conv_add2(rt, gt, bt, data[(pit>>2)+1]);
  87.         else                            conv_add2(rt, gt, bt, data[(pit>>2)  ]);
  88.     }
  89.  
  90.     rt = rt*m[0]+m[9];
  91.     gt = gt*m[0]+m[9];
  92.     bt = bt*m[0]+m[9];
  93.  
  94.     conv_add(rt, gt, bt, data[(pit>>2)  ],m[4]);
  95.  
  96.     rt>>=8;    if (rt<0) rt=0; else if (rt>255) rt=255;
  97.     gt>>=8;    if (gt<0) gt=0; else if (gt>255) gt=255;
  98.     bt>>=8;    if (bt<0) bt=0; else if (bt>255) bt=255;
  99.  
  100.     return (unsigned long)((rt<<16) | (gt<<8) | (bt));
  101. }
  102.  
  103. #ifndef USE_ASM
  104. static inline unsigned long do_conv2(unsigned long *data, long *m, long pit) {
  105.     long rt=0, gt=0, bt=0;
  106.  
  107.     conv_add2(rt, gt, bt, data[        -1]);
  108.     conv_add2(rt, gt, bt, data[         0]);
  109.     conv_add2(rt, gt, bt, data[        +1]);
  110.     conv_add2(rt, gt, bt, data[(pit>>2)-1]);
  111.     conv_add2(rt, gt, bt, data[(pit>>2)+1]);
  112.     conv_add2(rt, gt, bt, data[(pit>>1)-1]);
  113.     conv_add2(rt, gt, bt, data[(pit>>1)  ]);
  114.     conv_add2(rt, gt, bt, data[(pit>>1)+1]);
  115.     rt = rt*m[0]+m[9];
  116.     gt = gt*m[0]+m[9];
  117.     bt = bt*m[0]+m[9];
  118.  
  119.     conv_add(rt, gt, bt, data[(pit>>2)  ], m[4]);
  120.  
  121.     rt>>=8;    if (rt<0) rt=0; else if (rt>255) rt=255;
  122.     gt>>=8;    if (gt<0) gt=0; else if (gt>255) gt=255;
  123.     bt>>=8;    if (bt<0) bt=0; else if (bt>255) bt=255;
  124.  
  125.     return (unsigned long)((rt<<16) | (gt<<8) | (bt));
  126. }
  127. #endif
  128.  
  129. static int sharpen_run(const FilterActivation *fa, const FilterFunctions *ff) {
  130.     unsigned long w,h;
  131.     unsigned long *src = (unsigned long *)fa->src.data, *dst = (unsigned long *)fa->dst.data;
  132.     unsigned long pitch = fa->src.pitch;
  133.     long *m = ((ConvoluteFilterData *)(fa->filter_data))->m;
  134.  
  135.     src -= pitch>>2;
  136.  
  137.     *dst++ = do_conv(src++, m, C_BOTTOMOK | C_RIGHTOK, pitch);
  138.     w = fa->src.w-2;
  139.     do { *dst++ = do_conv(src++, m, C_BOTTOMOK | C_LEFTOK | C_RIGHTOK, pitch); } while(--w);
  140.     *dst++ = do_conv(src++, m, C_BOTTOMOK | C_LEFTOK, pitch);
  141.  
  142.     src += fa->src.modulo>>2;
  143.     dst += fa->dst.modulo>>2;
  144.  
  145. #ifdef USE_ASM
  146.     asm_sharpen_run(
  147.             dst+1,
  148.             src+1,
  149.             fa->src.w-2,
  150.             fa->src.h-2,
  151.             fa->src.pitch,
  152.             fa->dst.pitch,
  153.             m[0],
  154.             m[4]);
  155. #endif
  156.  
  157.     h = fa->src.h-2;
  158.     do {
  159.         *dst++ = do_conv(src++, m, C_TOPOK | C_BOTTOMOK | C_RIGHTOK, pitch);
  160. #ifdef USE_ASM
  161.         src += fa->src.w-2;
  162.         dst += fa->src.w-2;
  163. #else
  164.         w = fa->src.w-2;
  165.         do { *dst++ = do_conv2(src++, m, pitch); } while(--w);
  166. #endif
  167.         *dst++ = do_conv(src++, m, C_TOPOK | C_BOTTOMOK | C_LEFTOK, pitch);
  168.  
  169.         src += fa->src.modulo>>2;
  170.         dst += fa->dst.modulo>>2;
  171.     } while(--h);
  172.  
  173.     *dst++ = do_conv(src++, m, C_TOPOK | C_RIGHTOK, pitch);
  174.     w = fa->src.w-2;
  175.     do { *dst++ = do_conv(src++, m, C_TOPOK | C_LEFTOK | C_RIGHTOK, pitch); } while(--w);
  176.     *dst++ = do_conv(src++, m, C_TOPOK | C_LEFTOK, pitch);
  177.  
  178.     return 0;
  179. }
  180.  
  181. static long sharpen_param(FilterActivation *fa, const FilterFunctions *ff) {
  182.     return FILTERPARAM_SWAP_BUFFERS;
  183. }
  184.  
  185. static int sharpen_config(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd) {
  186.     ConvoluteFilterData *cfd;
  187.     LONG lv;
  188.     int i;
  189.  
  190.     if (!fa->filter_data) {
  191.         if (!(fa->filter_data = (void *)new ConvoluteFilterData)) return 0;
  192.         memset(fa->filter_data, 0, sizeof ConvoluteFilterData);
  193.         ((ConvoluteFilterData *)fa->filter_data)->m[4] = 256;
  194.     }
  195.     cfd = (ConvoluteFilterData *)fa->filter_data;
  196.  
  197.     lv = FilterGetSingleValue(hWnd, -cfd->m[0], 0, 64, "sharpen");
  198.  
  199.     for(i=0; i<9; i++)
  200.         if (i==4) cfd->m[4] = 256+8*lv; else cfd->m[i]=-lv;
  201.  
  202.     cfd->bias = -lv*4;
  203.  
  204.     return 0;
  205. }
  206.  
  207. static void sharpen_string(const FilterActivation *fa, const FilterFunctions *ff, char *buf) {
  208.     ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
  209.  
  210.     wsprintf(buf, " (by %ld)", -cfd->bias/4);
  211. }
  212.  
  213. static void sharpen_script_config(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  214.     FilterActivation *fa = (FilterActivation *)lpVoid;
  215.     int lv = argv[0].asInt();
  216.  
  217.     ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
  218.  
  219.     for(int i=0; i<9; i++)
  220.         if (i==4) cfd->m[4] = 256+8*lv; else cfd->m[i]=-lv;
  221.  
  222.     cfd->bias = -lv*4;
  223. }
  224.  
  225. static ScriptFunctionDef sharpen_func_defs[]={
  226.     { (ScriptFunctionPtr)sharpen_script_config, "Config", "0i" },
  227.     { NULL },
  228. };
  229.  
  230. static CScriptObject sharpen_obj={
  231.     NULL, sharpen_func_defs
  232. };
  233.  
  234. static bool sharpen_script_line(FilterActivation *fa, const FilterFunctions *ff, char *buf, int buflen) {
  235.     ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
  236.  
  237.     _snprintf(buf, buflen, "Config(%d)", -cfd->bias/4);
  238.  
  239.     return true;
  240. }
  241.  
  242. FilterDefinition filterDef_sharpen={
  243.     0,0,NULL,
  244.     "sharpen",
  245.     "Enhances contrast between adjacent elements in an image.\n\n[Assembly optimized] [MMX optimized]",
  246.     NULL,NULL,
  247.     sizeof(ConvoluteFilterData),
  248.     NULL,NULL,
  249.     sharpen_run,
  250.     sharpen_param,
  251.     sharpen_config,
  252.     sharpen_string,
  253.     NULL,
  254.     NULL,
  255.  
  256.     &sharpen_obj,
  257.     sharpen_script_line,
  258. };